﻿using Microsoft.AspNetCore.Mvc;
using NewLife.Caching;

namespace newlife.queue.api.Controllers
{
    /// <summary>
    /// Redis 队列操作（轻量级）
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class RedisQueueController(FullRedis fullRedis) : ControllerBase
    {
        public FullRedis Redis { get; } = fullRedis;

        [HttpPost]
        public IActionResult EasyPublish()
        {
            // 本质上是 Redis 中的 List 数据结构（先进先出）
            var queue = Redis.GetQueue<dynamic>("EasyQueue");

            int i = 1;
            while (true) 
            {
                queue.Add(new { id = i, name = "hechenyu" + i });

                Thread.Sleep(1000);
                i++;
            }
        }

        [HttpPost]
        public async Task<IActionResult> EasyConsume()
        {
            var queue = Redis.GetQueue<string>("EasyQueue");

            while (true)
            {
                var msg = await queue.TakeOneAsync(3); // 获取消息时最长等待 3 秒
                if (msg != null)
                {
                    Console.WriteLine("消费数据：" + msg);
                }

                Thread.Sleep(500);
            }
        }

        [HttpPost]
        public IActionResult AckPublish()
        {
            // 本质上是 Redis 中的 List 数据结构（先进先出）
            var queue = Redis.GetReliableQueue<dynamic>("AckQueue");

            int i = 1;
            while (true)
            {
                queue.Add(new { id = i, name = "hechenyu" + i });

                Thread.Sleep(1000);
                i++;
            }
        }

        [HttpPost]
        public async Task<IActionResult> AckConsume()
        {
            /*
             * 逻辑：
             * 1.Take 时将消息从 AckQueue 队列中取出，添加到可信队列 => AckQueue:Ack:*
             * 2.确认时将消息从可信队列删除
             * 3.可信队列的消息在 60 秒后会重新添加到 AckQueue 队列中
             * 
             * 思考：应该有个后台轮询，如果超过 60 秒将可信队列的消息全部添加到 AckQueue 队列
             */
            var queue = Redis.GetReliableQueue<string>("AckQueue");

            while (true)
            {
                var msg = await queue.TakeOneAsync(3);
                if (msg != null)
                {
                    Console.WriteLine("消费数据：" + msg);
                    queue.Acknowledge(msg); // 确认消息
                }

                Thread.Sleep(500);
            }
        }

        [HttpPost]
        public IActionResult DelayPublish()
        {
            // 本质上是 Redis 中的 Zset 数据结构（先进先出）
            var queue = Redis.GetDelayQueue<dynamic>("DelayQueue");

            int i = 1;
            while (true)
            {
                queue.Add(new { id = i, name = "hechenyu" + i }, 300);

                Thread.Sleep(1000);
                i++;
            }
        }

        [HttpPost]
        public async Task<IActionResult> DelayConsume()
        {
            /*
             * 逻辑：取的时候，找小于等于当前时间的 Score，获取 Member
             * 说明：发布的时候根据延迟时间，计算出什么时候才能消费的时间戳，存入 Score
             * 场景：快递存放超时收费、订单超时取消、会员到期通知
             */
            var queue = Redis.GetDelayQueue<string>("DelayQueue");

            while (true)
            {
                var msg = await queue.TakeOneAsync(3);
                if (msg != null)
                {
                    Console.WriteLine("消费数据：" + msg);
                }

                Thread.Sleep(500);
            }
        }

        [HttpPost]
        public IActionResult FullPublish()
        {
            // 本质上是 Redis 中的 Stream 数据结构（先进先出）
            var queue = Redis.GetStream<dynamic>("FullQueue");

            int i = 1;
            while (true)
            {
                queue.Add(new { id = i, name = "hechenyu" + i });

                Thread.Sleep(1000);
                i++;
            }
        }

        [HttpPost]
        public async Task<IActionResult> FullConsume()
        {
            /*
             * 逻辑：每个消息可以被不同的消费组消费一次（支持独立消费）
             */
            var queue = Redis.GetStream<string>("FullQueue");
            queue.Group = "Group1";

            while (true)
            {
                await queue.ConsumeAsync(Consume);
                Thread.Sleep(500);
            }

            static void Consume(string msg)
            {
                Console.WriteLine("消费数据：" + msg);
            }
        }
    }
}
